#include "preHeader.h"
#include "ClientSession.h"
#include "ClientSessionHandler.h"
#include "GameServerSession.h"
#include "SocialServerSession.h"
#include "ClientMgr.h"
#include "MapServerMgr.h"
#include "GateServer.h"
#include "Game/TransMgr.h"

ClientSession::ClientSession(uint32 sn)
: Session("ClientSession")
, m_sn(sn)
, m_lang(0)
, m_logicGsID(0)
, m_isAccountOK(false)
, m_acctId(0)
, m_isCharacterOK(false)
, m_charId(0)
, m_playerGuid(ObjGUID_NULL)
, m_isCharacterInMapServer(false)
, m_msSN(0)
{
}

ClientSession::~ClientSession()
{
}

int ClientSession::HandlePacket(INetPacket *pck)
{
	if (sClientSessionHandler.CanHandle(pck->GetOpcode())) {
		return sClientSessionHandler.HandlePacket(this, *pck);
	} else {
		return SessionHandleUnhandle;
	}
}

void ClientSession::OnManaged()
{
	NLOG("new client session [%s:%u](%u).",
		GetHost().c_str(), GetPort(), m_sn);
	sTransMgr.AddClient(this);
	sClientMgr.AddClient(this);
	Session::OnManaged();
}

void ClientSession::OnShutdownSession()
{
	WLOG("close client session [%s:%u](%u).",
		GetHost().c_str(), GetPort(), m_sn);
	sClientMgr.SendLogoutAccount2GameServer(this);
	sClientMgr.RemoveClient(this);
	sTransMgr.RemoveClient(this);
	Session::OnShutdownSession();
}

void ClientSession::SetAccountOK(uint32 acct)
{
	m_isAccountOK = true;
	m_acctId = acct;
}

void ClientSession::SetCharacterOnline(uint32 charId)
{
	m_isCharacterOK = true;
	m_charId = charId;
	m_playerGuid = GetGuidFromLowGuid4Player(charId);
}

void ClientSession::SetCharacterOffline()
{
	m_isCharacterOK = false;
	m_charId = 0;
	m_playerGuid = ObjGUID_NULL;
}

void ClientSession::SetCharacterEnterMapServer(uint32 msSN)
{
	m_isCharacterInMapServer = true;
	m_msSN = msSN;
}

void ClientSession::SetCharacterLeaveMapServer()
{
	m_isCharacterInMapServer = false;
	m_msSN = 0;
}

void ClientSession::OnRecvPacket(INetPacket *pck)
{
	const uint32 opcode = pck->GetOpcode();
	if (opcode > FLAG_MSG_NEED_LOGIN_CHARACTER_BEGIN && !IsCharacterOK()) {
		WLOG("FLAG_MSG_NEED_LOGIN_CHARACTER_BEGIN, %s:%hu, opcode %u.",
			GetHost().c_str(), GetPort(), opcode);
		delete pck;
		return;
	}
	if (opcode > FLAG_MSG_NEED_LOGIN_ACCOUNT_BEGIN && !IsAccountOK()) {
		WLOG("FLAG_MSG_NEED_LOGIN_ACCOUNT_BEGIN, %s:%hu, opcode %u.",
			GetHost().c_str(), GetPort(), opcode);
		delete pck;
		return;
	}

	if (sGameServerSession.CanHandle(opcode)) {
		sGameServerSession.TransPacket(m_acctId, *pck);
		delete pck;
		return;
	}

	if (sSocialServerSession.CanHandle(opcode)) {
		sSocialServerSession.TransPacket(m_charId, *pck);
		delete pck;
		return;
	}

	if (MapServerSession::CanHandle(opcode)) {
		if (IsCharacterInMapServer()) {
			auto pSession = sTransMgr.GetMapServer(m_msSN);
			if (pSession != NULL) {
				pSession->TransPacket(m_playerGuid, *pck);
				delete pck;
				return;
			} else {
				WLOG("MapServer can't found, %s:%hu, uid %u, msSN %u.",
					GetHost().c_str(), GetPort(), m_charId, m_msSN);
				delete pck;
				return;
			}
		} else {
			WLOG("Character isn't in mapserver, %s:%hu, uid %u, msSN %u.",
				GetHost().c_str(), GetPort(), m_charId, m_msSN);
			delete pck;
			return;
		}
	}

	Session::OnRecvPacket(pck);
}
